home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / transpor / ifmail23.z / ifmail23 / ifmail / ifcico / zmmisc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  19.3 KB  |  951 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  * 
  15.  *
  16.  *    This version implements numerous enhancements including ZMODEM
  17.  *    Run Length Encoding and variable length headers.  These
  18.  *    features were not funded by the original Telenet development
  19.  *    contract.
  20.  * 
  21.  * This software may be freely used for non commercial and
  22.  * educational (didactic only) purposes.  This software may also
  23.  * be freely used to support file transfer operations to or from
  24.  * licensed Omen Technology products.  Any programs which use
  25.  * part or all of this software must be provided in source form
  26.  * with this notice intact except by written permission from Omen
  27.  * Technology Incorporated.
  28.  * 
  29.  * Use of this software for commercial or administrative purposes
  30.  * except when exclusively limited to interfacing Omen Technology
  31.  * products requires a per port license payment of $20.00 US per
  32.  * port (less in quantity).  Use of this code by inclusion,
  33.  * decompilation, reverse engineering or any other means
  34.  * constitutes agreement to these conditions and acceptance of
  35.  * liability to license the materials and payment of reasonable
  36.  * legal costs necessary to enforce this license agreement.
  37.  *
  38.  *
  39.  *        Omen Technology Inc        FAX: 503-621-3745
  40.  *        Post Office Box 4681
  41.  *        Portland OR 97208
  42.  *
  43.  *    This code is made available in the hope it will be useful,
  44.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  45.  *    DAMAGES OF ANY KIND.
  46.  *
  47.  */
  48.  
  49. static void zputhex(int);
  50. static void zsbh32(int,char*,int,int);
  51. static void zsda32(char*,int,int);
  52. static int zrdat32(char*,int);
  53. static int noxrd7(void);
  54. static int zrbhd32(char*);
  55. static int zrbhdr(char*);
  56. static int zrhhdr(char*);
  57. static int zgethex(void);
  58. static int zgeth1(void);
  59. static void garbitch(void);
  60.  
  61. #include <stdio.h>
  62. #include "xutil.h"
  63. #include "lutil.h"
  64. #include "ttyio.h"
  65. #include "zmodem.h"
  66. static int Rxtimeout = 20;    /* Tenths of seconds to wait for something */
  67. int Zctlesc;
  68.  
  69. /* Globals used by ZMODEM functions */
  70. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  71. int Rxtype;        /* Type of header received */
  72. int Rxhlen;        /* Length of header received */
  73. int Rxcount;        /* Count of data bytes received */
  74. char Rxhdr[ZMAXHLEN];    /* Received header */
  75. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  76. long Rxpos;        /* Received file position */
  77. long Txpos;        /* Transmitted file position */
  78. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  79. int Crc32t;        /* Controls 32 bit CRC being sent */
  80.             /* 1 == CRC32,  2 == CRC32 + RLE */
  81. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  82.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  83. int Usevhdrs;        /* Use variable length headers */
  84. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  85. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  86. char *Altcan;        /* Alternate canit string */
  87.  
  88. char *txbuf=NULL;
  89. char *rxbuf=NULL;
  90.  
  91. static lastsent;    /* Last char we sent */
  92. static Not8bit;        /* Seven bits seen on header */
  93.  
  94. char *frametypes[] = {
  95.     "EMPTY",        /* -16 */
  96.     "Can't be (-15)",
  97.     "Can't be (-14)",
  98.     "Can't be (-13)",
  99.     "Can't be (-12)",
  100.     "Can't be (-11)",
  101.     "Can't be (-10)",
  102.     "Can't be (-9)",
  103.     "HANGUP",        /* -8 */
  104.     "Can't be (-7)",
  105.     "Can't be (-6)",
  106.     "Can't be (-5)",
  107.     "EOFILE",        /* -4 */
  108.     "Can't be (-3)",
  109.     "TIMEOUT",        /* -2 */
  110.     "ERROR",        /* -1 */
  111.     "ZRQINIT",
  112.     "ZRINIT",
  113.     "ZSINIT",
  114.     "ZACK",
  115.     "ZFILE",
  116.     "ZSKIP",
  117.     "ZNAK",
  118.     "ZABORT",
  119.     "ZFIN",
  120.     "ZRPOS",
  121.     "ZDATA",
  122.     "ZEOF",
  123.     "ZFERR",
  124.     "ZCRC",
  125.     "ZCHALLENGE",
  126.     "ZCOMPL",
  127.     "ZCAN",
  128.     "ZFREECNT",
  129.     "ZCOMMAND",
  130.     "ZSTDERR",
  131.     "xxxxx"
  132. #define FRTYPES 22    /* Total number of frame types in this array */
  133.             /*  not including psuedo negative entries */
  134. };
  135.  
  136. static char badcrc[] = "Bad CRC";
  137.  
  138. /**** I am including this fix as a temporary solution... Gonna got the 
  139.       entire zmodem rewritten some day.  = E.C.
  140. ****/
  141.  
  142. /***** Hack by mj ***********************************************************/
  143. /*
  144.  * Buffer for outgoing frames. Sending them with single character write()'s
  145.  * is a waste of processor time and causes severe performance degradation
  146.  * on TCP and ISDN connections.
  147.  */
  148. #define FRAME_BUFFER_SIZE    16384
  149. static char *frame_buffer=NULL;
  150. static int  frame_length = 0;
  151.  
  152. #define BUFFER_CLEAR()    do { frame_length=0; } while(0)
  153. #define BUFFER_BYTE(c)    do { frame_buffer[frame_length++]=(c); } while(0)
  154. #define BUFFER_FLUSH()    do { PUT(frame_buffer, frame_length); \
  155.                  frame_length=0; } while(0);
  156. /****************************************************************************/
  157.  
  158. void get_frame_buffer(void)
  159. {
  160.     if (frame_buffer == NULL) frame_buffer=xmalloc(FRAME_BUFFER_SIZE);
  161. }
  162.  
  163. /* Send ZMODEM binary header hdr of type type */
  164. void zsbhdr(len, type, hdr)
  165. int len,type;
  166. register char *hdr;
  167. {
  168.     register int n;
  169.     register unsigned short crc;
  170.  
  171.     debug(11,"zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  172.       frametypes[type+FTOFFSET], rclhdr(hdr));
  173.  
  174.     BUFFER_CLEAR();
  175.     
  176.     if (type == ZDATA)
  177.         for (n = Znulls; --n >=0; )
  178.             BUFFER_BYTE(0);
  179.  
  180.     BUFFER_BYTE(ZPAD); BUFFER_BYTE(ZDLE);
  181.  
  182.     switch (Crc32t=Txfcs32) {
  183.     case 2:
  184.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  185.     case 1:
  186.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  187.     default:
  188.         if (Usevhdrs) {
  189.             BUFFER_BYTE(ZVBIN);
  190.             zsendline(len);
  191.         }
  192.         else
  193.             BUFFER_BYTE(ZBIN);
  194.         zsendline(type);
  195.         crc = updcrc16(type, 0);
  196.  
  197.         for (n=len; --n >= 0; ++hdr) {
  198.             zsendline(*hdr);
  199.             crc = updcrc16((0377& *hdr), crc);
  200.         }
  201.         crc = updcrc16(0,updcrc16(0,crc));
  202.         zsendline(crc>>8);
  203.         zsendline(crc);
  204.     }
  205.  
  206.     BUFFER_FLUSH();
  207. }
  208.  
  209.  
  210. /* Send ZMODEM binary header hdr of type type */
  211. void zsbh32(len, hdr, type, flavour)
  212. int len;
  213. register char *hdr;
  214. int type,flavour;
  215. {
  216.     register int n;
  217.     register long crc;
  218.  
  219.     BUFFER_BYTE(flavour); 
  220.     if (Usevhdrs) 
  221.         zsendline(len);
  222.     zsendline(type);
  223.     crc = 0xFFFFFFFFL; crc = updcrc32(type, crc);
  224.  
  225.     for (n=len; --n >= 0; ++hdr) {
  226.         crc = updcrc32((0377 & *hdr), crc);
  227.         zsendline(*hdr);
  228.     }
  229.     crc = ~crc;
  230.     for (n=4; --n >= 0;) {
  231.         zsendline((int)crc);
  232.         crc >>= 8;
  233.     }
  234. }
  235.  
  236. /* Send ZMODEM HEX header hdr of type type */
  237. void zshhdr(len, type, hdr)
  238. int len,type;
  239. register char *hdr;
  240. {
  241.     register int n;
  242.     register unsigned short crc;
  243.  
  244.     debug(11,"zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  245.       frametypes[type+FTOFFSET], rclhdr(hdr));
  246.  
  247.  
  248.     BUFFER_CLEAR();
  249.     
  250.     BUFFER_BYTE(ZPAD); BUFFER_BYTE(ZPAD); BUFFER_BYTE(ZDLE);
  251.     if (Usevhdrs) {
  252.         BUFFER_BYTE(ZVHEX);
  253.         zputhex(len);
  254.     }
  255.     else
  256.         BUFFER_BYTE(ZHEX);
  257.     zputhex(type);
  258.     Crc32t = 0;
  259.  
  260.     crc = updcrc16(type, 0);
  261.     for (n=len; --n >= 0; ++hdr) {
  262.         zputhex(*hdr); crc = updcrc16((0377 & *hdr), crc);
  263.     }
  264.     crc = updcrc16(0,updcrc16(0,crc));
  265.     zputhex(crc>>8); zputhex(crc);
  266.  
  267.     /* Make it printable on remote machine */
  268.     BUFFER_BYTE(015); BUFFER_BYTE(0212);
  269.     /*
  270.      * Uncork the remote in case a fake XOFF has stopped data flow
  271.      */
  272.     if (type != ZFIN && type != ZACK)
  273.         BUFFER_BYTE(021);
  274.  
  275.     BUFFER_FLUSH();
  276. }
  277.  
  278. /*
  279.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  280.  */
  281. char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  282. void zsdata(buf, length, frameend)
  283. register char *buf;
  284. int length,frameend;
  285. {
  286.     register unsigned short crc;
  287.  
  288.     debug(11,"zsdata: %d %s", length, Zendnames[(frameend-ZCRCE)&3]);
  289.  
  290.  
  291.     BUFFER_CLEAR();
  292.     
  293.     switch (Crc32t) {
  294.     case 1:
  295.         zsda32(buf, length, frameend);  break;
  296. /**
  297.     case 2:
  298.         zsdar32(buf, length, frameend);  break;
  299. **/
  300.     default:
  301.         crc = 0;
  302.         for (;--length >= 0; ++buf) {
  303.             zsendline(*buf); crc = updcrc16((0377 & *buf), crc);
  304.         }
  305.         BUFFER_BYTE(ZDLE); BUFFER_BYTE(frameend);
  306.         crc = updcrc16(frameend, crc);
  307.  
  308.         crc = updcrc16(0,updcrc16(0,crc));
  309.         zsendline(crc>>8); zsendline(crc);
  310.     }
  311.     if (frameend == ZCRCW)
  312.         BUFFER_BYTE(DC1);
  313.  
  314.     BUFFER_FLUSH();
  315. }
  316.  
  317. void zsda32(buf, length, frameend)
  318. register char *buf;
  319. int length,frameend;
  320. {
  321.     register int c;
  322.     register long crc;
  323.  
  324.     crc = 0xFFFFFFFFL;
  325.     for (;--length >= 0; ++buf) {
  326.         c = *buf & 0377;
  327.         if (c & 0140)
  328.             BUFFER_BYTE(lastsent = c);
  329.         else
  330.             zsendline(c);
  331.         crc = updcrc32(c, crc);
  332.     }
  333.     BUFFER_BYTE(ZDLE); BUFFER_BYTE(frameend);
  334.     crc = updcrc32(frameend, crc);
  335.  
  336.     crc = ~crc;
  337.     for (c=4; --c >= 0;) {
  338.         zsendline((int)crc);  crc >>= 8;
  339.     }
  340. }
  341.  
  342. /*
  343.  * Receive array buf of max length with ending ZDLE sequence
  344.  *  and CRC.  Returns the ending character or error code.
  345.  *  NB: On errors may store length+1 bytes!
  346.  */
  347. int zrdata(buf, length)
  348. register char *buf;
  349. int length;
  350. {
  351.     register int c;
  352.     register unsigned short crc;
  353.     register char *end;
  354.     register int d;
  355.  
  356.     switch (Crc32r) {
  357.     case 1:
  358.         return zrdat32(buf, length);
  359. /**
  360.     case 2:
  361.         return zrdatr32(buf, length);
  362. **/
  363.     }
  364.  
  365.     crc = Rxcount = 0;  end = buf + length;
  366.     while (buf <= end) {
  367.         if ((c = zdlread()) & ~0377) {
  368. crcfoo:
  369.             switch (c) {
  370.             case GOTCRCE:
  371.             case GOTCRCG:
  372.             case GOTCRCQ:
  373.             case GOTCRCW:
  374.                 crc = updcrc16((((d=c))&0377), crc);
  375.                 if ((c = zdlread()) & ~0377)
  376.                     goto crcfoo;
  377.                 crc = updcrc16(c, crc);
  378.                 if ((c = zdlread()) & ~0377)
  379.                     goto crcfoo;
  380.                 crc = updcrc16(c, crc);
  381.                 if (crc & 0xFFFF) {
  382.                     loginf(badcrc);
  383.                     return ERROR;
  384.                 }
  385.                 Rxcount = length - (end - buf);
  386.  
  387.                 debug(11,"zrdata: %d  %s", Rxcount,
  388.                  Zendnames[(d-GOTCRCE)&3]);
  389.  
  390.                 return d;
  391.             case GOTCAN:
  392.                 loginf("Sender Canceled");
  393.                 return ZCAN;
  394.             case TIMEOUT:
  395.                 loginf("TIMEOUT receiving data");
  396.                 return c;
  397.             case HANGUP:
  398.                 loginf("Carrier lost while receiving");
  399.                 return c;
  400.             default:
  401.                 garbitch(); return c;
  402.             }
  403.         }
  404.         *buf++ = c;
  405.         crc = updcrc16(c, crc);
  406.     }
  407.     loginf("Data subpacket too long");
  408.     return ERROR;
  409. }
  410.  
  411. int zrdat32(buf, length)
  412. register char *buf;
  413. int length;
  414. {
  415.     register int c;
  416.     register long crc;
  417.     register char *end;
  418.     register int d;
  419.  
  420.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  421.     while (buf <= end) {
  422.         if ((c = zdlread()) & ~0377) {
  423. crcfoo:
  424.             switch (c) {
  425.             case GOTCRCE:
  426.             case GOTCRCG:
  427.             case GOTCRCQ:
  428.             case GOTCRCW:
  429.                 d = c;  c &= 0377;
  430.                 crc = updcrc32(c, crc);
  431.                 if ((c = zdlread()) & ~0377)
  432.                     goto crcfoo;
  433.                 crc = updcrc32(c, crc);
  434.                 if ((c = zdlread()) & ~0377)
  435.                     goto crcfoo;
  436.                 crc = updcrc32(c, crc);
  437.                 if ((c = zdlread()) & ~0377)
  438.                     goto crcfoo;
  439.                 crc = updcrc32(c, crc);
  440.                 if ((c = zdlread()) & ~0377)
  441.                     goto crcfoo;
  442.                 crc = updcrc32(c, crc);
  443.                 if (crc != 0xDEBB20E3) {
  444.                     loginf(badcrc);
  445.                     return ERROR;
  446.                 }
  447.                 Rxcount = length - (end - buf);
  448.  
  449.                 debug(11,"zrdat32: %d %s", Rxcount,
  450.                  Zendnames[(d-GOTCRCE)&3]);
  451.  
  452.                 return d;
  453.             case GOTCAN:
  454.                 loginf("Sender Canceled");
  455.                 return ZCAN;
  456.             case TIMEOUT:
  457.                 loginf("TIMEOUT");
  458.                 return c;
  459.             case HANGUP:
  460.                 loginf("Carrier lost while receiving");
  461.                 return c;
  462.             default:
  463.                 garbitch(); return c;
  464.             }
  465.         }
  466.         *buf++ = c;
  467.         crc = updcrc32(c, crc);
  468.     }
  469.     loginf("Data subpacket too long");
  470.     return ERROR;
  471. }
  472.  
  473. void garbitch(void)
  474. {
  475.     loginf("Garbled data subpacket");
  476. }
  477.  
  478. /*
  479.  * Read a ZMODEM header to hdr, either binary or hex.
  480.  *  eflag controls local display of non zmodem characters:
  481.  *    0:  no display
  482.  *    1:  display printing characters only
  483.  *    2:  display all non ZMODEM characters
  484.  *
  485.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  486.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  487.  *   Otherwise return negative on error.
  488.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  489.  */
  490. int zgethdr(hdr, eflag)
  491. char *hdr;
  492. int eflag;
  493. {
  494.     register int c, n, cancount;
  495.  
  496.     Rxframeind = Rxtype = 0;
  497.  
  498. startover:
  499.     cancount = 5;
  500. again:
  501.     /* Return immediate ERROR if ZCRCW sequence seen */
  502.     TTYWAIT(1);
  503.     if (((c = GETCHAR(Rxtimeout)) < 0) && (c != TIMEOUT))
  504.         goto fifi;
  505.     else switch (c) {
  506.     case 021: case 0221:
  507.         goto again;
  508.     case CAN:
  509. gotcan:
  510.         if (--cancount <= 0) {
  511.             c = ZCAN; goto fifi;
  512.         }
  513.         switch (c = GETCHAR(1)) {
  514.         case TIMEOUT:
  515.             goto again;
  516.         case ZCRCW:
  517.             switch (GETCHAR(1)) {
  518.             case TIMEOUT:
  519.                 c = ERROR; goto fifi;
  520.             case HANGUP:
  521.                 goto fifi;
  522.             default:
  523.                 goto agn2;
  524.             }
  525.         case HANGUP:
  526.             goto fifi;
  527.         default:
  528.             break;
  529.         case CAN:
  530.             if (--cancount <= 0) {
  531.                 c = ZCAN; goto fifi;
  532.             }
  533.             goto again;
  534.         }
  535.     /* **** FALL THRU TO **** */
  536.     default:
  537. agn2:
  538.         goto startover;
  539.     case ZPAD|0200:        /* This is what we want. */
  540.         Not8bit = c;
  541.     case ZPAD:        /* This is what we want. */
  542.         break;
  543.     }
  544.     cancount = 5;
  545. splat:
  546.     switch (c = noxrd7()) {
  547.     case ZPAD:
  548.         goto splat;
  549.     case HANGUP:
  550.     case TIMEOUT:
  551.         goto fifi;
  552.     default:
  553.         goto agn2;
  554.     case ZDLE:        /* This is what we want. */
  555.         break;
  556.     }
  557.  
  558.  
  559.     Rxhlen = 4;        /* Set default length */
  560.     Rxframeind = c = noxrd7();
  561.     switch (c) {
  562.     case ZVBIN32:
  563.         if ((Rxhlen = c = zdlread()) < 0)
  564.             goto fifi;
  565.         if (c > ZMAXHLEN)
  566.             goto agn2;
  567.         Crc32r = 1;  c = zrbhd32(hdr); break;
  568.     case ZBIN32:
  569.         if (Usevhdrs)
  570.             goto agn2;
  571.         Crc32r = 1;  c = zrbhd32(hdr); break;
  572.     case ZVBINR32:
  573.         if ((Rxhlen = c = zdlread()) < 0)
  574.             goto fifi;
  575.         if (c > ZMAXHLEN)
  576.             goto agn2;
  577.         Crc32r = 2;  c = zrbhd32(hdr); break;
  578.     case ZBINR32:
  579.         if (Usevhdrs)
  580.             goto agn2;
  581.         Crc32r = 2;  c = zrbhd32(hdr); break;
  582.     case HANGUP:
  583.     case TIMEOUT:
  584.         goto fifi;
  585.     case ZVBIN:
  586.         if ((Rxhlen = c = zdlread()) < 0)
  587.             goto fifi;
  588.         if (c > ZMAXHLEN)
  589.             goto agn2;
  590.         Crc32r = 0;  c = zrbhdr(hdr); break;
  591.     case ZBIN:
  592.         if (Usevhdrs)
  593.             goto agn2;
  594.         Crc32r = 0;  c = zrbhdr(hdr); break;
  595.     case ZVHEX:
  596.         if ((Rxhlen = c = zgethex()) < 0)
  597.             goto fifi;
  598.         if (c > ZMAXHLEN)
  599.             goto agn2;
  600.         Crc32r = 0;  c = zrhhdr(hdr); break;
  601.     case ZHEX:
  602.         if (Usevhdrs)
  603.             goto agn2;
  604.         Crc32r = 0;  c = zrhhdr(hdr); break;
  605.     case CAN:
  606.         goto gotcan;
  607.     default:
  608.         goto agn2;
  609.     }
  610.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  611.         hdr[n] = 0;
  612.     Rxpos = hdr[ZP3] & 0377;
  613.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  614.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  615.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  616. fifi:
  617.     switch (c) {
  618.     case GOTCAN:
  619.         c = ZCAN;
  620.     /* **** FALL THRU TO **** */
  621.     case ZNAK:
  622.     case ZCAN:
  623.     case ERROR:
  624.     case TIMEOUT:
  625.     case HANGUP:
  626.     default:
  627.         if (c >= -FTOFFSET && c <= FRTYPES)
  628.             debug(11,"zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  629.               frametypes[c+FTOFFSET], Rxpos);
  630.         else
  631.             debug(11,"zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  632.     }
  633.     /* Use variable length headers if we got one */
  634.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  635.         Usevhdrs = 1;
  636.     return c;
  637. }
  638.  
  639. /* Receive a binary style header (type and position) */
  640. int zrbhdr(hdr)
  641. register char *hdr;
  642. {
  643.     register int c, n;
  644.     register unsigned short crc;
  645.  
  646.     if ((c = zdlread()) & ~0377)
  647.         return c;
  648.     Rxtype = c;
  649.     crc = updcrc16(c, 0);
  650.  
  651.     for (n=Rxhlen; --n >= 0; ++hdr) {
  652.         if ((c = zdlread()) & ~0377)
  653.             return c;
  654.         crc = updcrc16(c, crc);
  655.         *hdr = c;
  656.     }
  657.     if ((c = zdlread()) & ~0377)
  658.         return c;
  659.     crc = updcrc16(c, crc);
  660.     if ((c = zdlread()) & ~0377)
  661.         return c;
  662.     crc = updcrc16(c, crc);
  663.     if (crc & 0xFFFF) {
  664.         loginf(badcrc);
  665.         return ERROR;
  666.     }
  667.     return Rxtype;
  668. }
  669.  
  670. /* Receive a binary style header (type and position) with 32 bit FCS */
  671. int zrbhd32(hdr)
  672. register char *hdr;
  673. {
  674.     register int c, n;
  675.     register long crc;
  676.  
  677.     if ((c = zdlread()) & ~0377)
  678.         return c;
  679.     Rxtype = c;
  680.     crc = 0xFFFFFFFFL; crc = updcrc32(c, crc);
  681.  
  682.     debug(11,"zrbhd32 c=%X  crc=%lX", c, crc);
  683.  
  684.     for (n=Rxhlen; --n >= 0; ++hdr) {
  685.         if ((c = zdlread()) & ~0377)
  686.             return c;
  687.         crc = updcrc32(c, crc);
  688.         *hdr = c;
  689.  
  690.         debug(11,"zrbhd32 c=%X  crc=%lX", c, crc);
  691.     }
  692.     for (n=4; --n >= 0;) {
  693.         if ((c = zdlread()) & ~0377)
  694.             return c;
  695.         crc = updcrc32(c, crc);
  696.  
  697.         debug(11,"zrbhd32 c=%X  crc=%lX", c, crc);
  698.     }
  699.     if (crc != 0xDEBB20E3) {
  700.         loginf(badcrc);
  701.         return ERROR;
  702.     }
  703.     return Rxtype;
  704. }
  705.  
  706.  
  707. /* Receive a hex style header (type and position) */
  708. int zrhhdr(hdr)
  709. char *hdr;
  710. {
  711.     register int c;
  712.     register unsigned short crc;
  713.     register int n;
  714.  
  715.     if ((c = zgethex()) < 0)
  716.         return c;
  717.     Rxtype = c;
  718.     crc = updcrc16(c, 0);
  719.  
  720.     for (n=Rxhlen; --n >= 0; ++hdr) {
  721.         if ((c = zgethex()) < 0)
  722.             return c;
  723.         crc = updcrc16(c, crc);
  724.         *hdr = c;
  725.     }
  726.     if ((c = zgethex()) < 0)
  727.         return c;
  728.     crc = updcrc16(c, crc);
  729.     if ((c = zgethex()) < 0)
  730.         return c;
  731.     crc = updcrc16(c, crc);
  732.     if (crc & 0xFFFF) {
  733.         loginf(badcrc); return ERROR;
  734.     }
  735.     switch ( c = GETCHAR(2)) {
  736.     case 0215:
  737.         Not8bit = c;
  738.         /* **** FALL THRU TO **** */
  739.     case 015:
  740.          /* Throw away possible cr/lf */
  741.         switch (c = GETCHAR(2)) {
  742.         case 012:
  743.             Not8bit |= c;
  744.         }
  745.     }
  746.     if (c < 0)
  747.         return c;
  748.     return Rxtype;
  749. }
  750.  
  751. /* Send a byte as two hex digits */
  752. void zputhex(c)
  753. register int c;
  754. {
  755.     static char    digits[]    = "0123456789abcdef";
  756.  
  757.     debug(19,"zputhex: %02X", c);
  758.  
  759.     BUFFER_BYTE(digits[(c&0xF0)>>4]);
  760.     BUFFER_BYTE(digits[(c)&0xF]);
  761. }
  762.  
  763. /*
  764.  * Send character c with ZMODEM escape sequence encoding.
  765.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  766.  */
  767. void zsendline(c)
  768. int c;
  769. {
  770.  
  771.     /* Quick check for non control characters */
  772.     if (c & 0140)
  773.         BUFFER_BYTE(lastsent = c);
  774.     else {
  775.         switch (c &= 0377) {
  776.         case ZDLE:
  777.             BUFFER_BYTE(ZDLE);
  778.             BUFFER_BYTE (lastsent = (c ^= 0100));
  779.             break;
  780.         case 015:
  781.         case 0215:
  782.             if (!Zctlesc && (lastsent & 0177) != '@')
  783.                 goto sendit;
  784.         /* **** FALL THRU TO **** */
  785.         case 020:
  786.         case 021:
  787.         case 023:
  788.         case 0220:
  789.         case 0221:
  790.         case 0223:
  791.             BUFFER_BYTE(ZDLE);
  792.             c ^= 0100;
  793.     sendit:
  794.             BUFFER_BYTE(lastsent = c);
  795.             break;
  796.         default:
  797.             if (Zctlesc && ! (c & 0140)) {
  798.                 BUFFER_BYTE(ZDLE);
  799.                 c ^= 0100;
  800.             }
  801.             BUFFER_BYTE(lastsent = c);
  802.         }
  803.     }
  804. }
  805.  
  806. /* Decode two lower case hex digits into an 8 bit byte value */
  807. int zgethex(void)
  808. {
  809.     register int c;
  810.  
  811.     c = zgeth1();
  812.     debug(19,"zgethex: %02X", c);
  813.     return c;
  814. }
  815. int zgeth1(void)
  816. {
  817.     register int c, n;
  818.  
  819.     if ((c = noxrd7()) < 0)
  820.         return c;
  821.     n = c - '0';
  822.     if (n > 9)
  823.         n -= ('a' - ':');
  824.     if (n & ~0xF)
  825.         return ERROR;
  826.     if ((c = noxrd7()) < 0)
  827.         return c;
  828.     c -= '0';
  829.     if (c > 9)
  830.         c -= ('a' - ':');
  831.     if (c & ~0xF)
  832.         return ERROR;
  833.     c += (n<<4);
  834.     return c;
  835. }
  836.  
  837. /*
  838.  * Read a byte, checking for ZMODEM escape encoding
  839.  *  including CAN*5 which represents a quick abort
  840.  */
  841. int zdlread(void)
  842. {
  843.     register int c;
  844.  
  845. again:
  846.     /* Quick check for non control characters */
  847.     if ((c = GETCHAR(Rxtimeout)) & 0140)
  848.         return c;
  849.     switch (c) {
  850.     case ZDLE:
  851.         break;
  852.     case 023:
  853.     case 0223:
  854.     case 021:
  855.     case 0221:
  856.         goto again;
  857.     default:
  858.         if (Zctlesc && !(c & 0140)) {
  859.             goto again;
  860.         }
  861.         return c;
  862.     }
  863. again2:
  864.     if ((c = GETCHAR(Rxtimeout)) < 0)
  865.         return c;
  866.     if (c == CAN && (c = GETCHAR(Rxtimeout)) < 0)
  867.         return c;
  868.     if (c == CAN && (c = GETCHAR(Rxtimeout)) < 0)
  869.         return c;
  870.     if (c == CAN && (c = GETCHAR(Rxtimeout)) < 0)
  871.         return c;
  872.     switch (c) {
  873.     case CAN:
  874.         return GOTCAN;
  875.     case ZCRCE:
  876.     case ZCRCG:
  877.     case ZCRCQ:
  878.     case ZCRCW:
  879.         return (c | GOTOR);
  880.     case ZRUB0:
  881.         return 0177;
  882.     case ZRUB1:
  883.         return 0377;
  884.     case 023:
  885.     case 0223:
  886.     case 021:
  887.     case 0221:
  888.         goto again2;
  889.     default:
  890.         if (Zctlesc && ! (c & 0140)) {
  891.             goto again2;
  892.         }
  893.         if ((c & 0140) ==  0100)
  894.             return (c ^ 0100);
  895.         break;
  896.     }
  897.     debug(11,"Bad escape sequence %x", c);
  898.     return ERROR;
  899. }
  900.  
  901. /*
  902.  * Read a character from the modem line with timeout.
  903.  *  Eat parity, XON and XOFF characters.
  904.  */
  905. int noxrd7(void)
  906. {
  907.     register int c;
  908.  
  909.     for (;;) {
  910.         if ((c = GETCHAR(Rxtimeout)) < 0)
  911.             return c;
  912.         switch (c &= 0177) {
  913.         case DC1:
  914.         case DC3:
  915.             continue;
  916.         default:
  917.             if (Zctlesc && !(c & 0140))
  918.                 continue;
  919.         case '\r':
  920.         case '\n':
  921.         case ZDLE:
  922.             return c;
  923.         }
  924.     }
  925. }
  926.  
  927. /* Store long integer pos in Txhdr */
  928. void stohdr(pos)
  929. long pos;
  930. {
  931.     Txhdr[ZP0] = pos;
  932.     Txhdr[ZP1] = pos>>8;
  933.     Txhdr[ZP2] = pos>>16;
  934.     Txhdr[ZP3] = pos>>24;
  935. }
  936.  
  937. /* Recover a long integer from a header */
  938. long rclhdr(hdr)
  939. register char *hdr;
  940. {
  941.     register long l;
  942.  
  943.     l = (hdr[ZP3] & 0377);
  944.     l = (l << 8) | (hdr[ZP2] & 0377);
  945.     l = (l << 8) | (hdr[ZP1] & 0377);
  946.     l = (l << 8) | (hdr[ZP0] & 0377);
  947.     return l;
  948. }
  949.  
  950. /* End of zmmisc.c */
  951.